﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.IntelliTrace;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Globalization;

namespace Microsoft.VisualStudio.Samples.ConsoleWriters
{
    public class ProcessChainConsoleWriter : ChainConsoleWriter
    {

        public void CollectionPlanEvent(IntelliTraceEvent ev)
        {
            CollectionPlanEvent collectionPlanEvent = ev as CollectionPlanEvent;
            Debug.Assert(collectionPlanEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", collectionPlanEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Collection plan", collectionPlanEvent.CollectionPlan.Substring(0, 50));

            DumpProperties(eventProperties);
        }

        public void SystemInfoEvent(IntelliTraceEvent ev)
        {
            SystemInformationEvent systemInfoEvent = ev as SystemInformationEvent;
            Debug.Assert(systemInfoEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", systemInfoEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("System manufacturer", systemInfoEvent.SystemManufacturer);
            eventProperties.Add("System product name", systemInfoEvent.SystemProductName);
            eventProperties.Add("Bios version", systemInfoEvent.BiosVersion);
            eventProperties.Add("Bios date", systemInfoEvent.BiosDate);
            eventProperties.Add("Processor architecture", systemInfoEvent.ProcessorArchitecture.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("And more", "...");

            DumpProperties(eventProperties);
        }

        public void ModuleLoadEvent(IntelliTraceEvent ev)
        {
            ModuleLoadEvent moduleLoadEvent = ev as ModuleLoadEvent;
            Debug.Assert(moduleLoadEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", moduleLoadEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Event time", GetDateTimeFromEventTime(this.Process, moduleLoadEvent.EventTime).ToString("HH:mm:ss.fffffff", CultureInfo.CurrentCulture));
            eventProperties.Add("Module name", moduleLoadEvent.Name);
            eventProperties.Add("Mvid", moduleLoadEvent.Mvid.ToString());
            eventProperties.Add("Module id", moduleLoadEvent.ModuleId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Base load address", string.Format(CultureInfo.CurrentCulture, "0x{0:x16}", moduleLoadEvent.BaseLoadAddress));

            DumpProperties(eventProperties);
        }

        public void ModuleUnloadEvent(IntelliTraceEvent ev)
        {
            ModuleUnloadEvent moduleUnloadEvent = ev as ModuleUnloadEvent;
            Debug.Assert(moduleUnloadEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", moduleUnloadEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Event time", GetDateTimeFromEventTime(this.Process, moduleUnloadEvent.EventTime).ToString("HH:mm:ss.fffffff", CultureInfo.CurrentCulture));
            eventProperties.Add("Module id", moduleUnloadEvent.ModuleId.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ThreadCreateEvent(IntelliTraceEvent ev)
        {
            ThreadCreateEvent threadCreateEvent = ev as ThreadCreateEvent;
            Debug.Assert(threadCreateEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", threadCreateEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Event time", GetDateTimeFromEventTime(this.Process, threadCreateEvent.EventTime).ToString("HH:mm:ss.fffffff", CultureInfo.CurrentCulture));
            eventProperties.Add("Name", threadCreateEvent.Name);
            eventProperties.Add("Thread id", threadCreateEvent.IntelliTraceThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Managed thread id", threadCreateEvent.ManagedThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Native thread id", threadCreateEvent.NativeThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Priority", threadCreateEvent.PriorityName);
            eventProperties.Add("Category", threadCreateEvent.Category.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ThreadDestroyEvent(IntelliTraceEvent ev)
        {
            ThreadDestroyEvent threadDestroyEvent = ev as ThreadDestroyEvent;
            Debug.Assert(threadDestroyEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", threadDestroyEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Event time", GetDateTimeFromEventTime(this.Process, threadDestroyEvent.EventTime).ToString("HH:mm:ss.fffffff", CultureInfo.CurrentCulture));
            eventProperties.Add("Thread id", threadDestroyEvent.IntelliTraceThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Managed thread id", threadDestroyEvent.ManagedThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Native thread id", threadDestroyEvent.NativeThreadId.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ThreadNameChangedEvent(IntelliTraceEvent ev)
        {
            ThreadNameChangedEvent threadNameChangedEvent = ev as ThreadNameChangedEvent;
            Debug.Assert(threadNameChangedEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", threadNameChangedEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Name", threadNameChangedEvent.ThreadName);
            eventProperties.Add("Thread id", threadNameChangedEvent.IntelliTraceThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Managed thread id", threadNameChangedEvent.ManagedThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Native thread id", threadNameChangedEvent.NativeThreadId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Category", threadNameChangedEvent.Category.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ProcessDestroyedEvent(IntelliTraceEvent ev)
        {
            ProcessDestroyedEvent processDestroyedEvent = ev as ProcessDestroyedEvent;
            Debug.Assert(processDestroyedEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", processDestroyedEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Event time", GetDateTimeFromEventTime(this.Process, processDestroyedEvent.EventTime).ToString("HH:mm:ss.fffffff", CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ModuleTokenEvent(IntelliTraceEvent ev)
        {
            ModuleTokenEvent moduleTokenEvent = ev as ModuleTokenEvent;
            Debug.Assert(moduleTokenEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", moduleTokenEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Trace debug token", moduleTokenEvent.MethodToken.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Module id", moduleTokenEvent.ModuleId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Method def token", moduleTokenEvent.MetadataToken.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }

        public void ModuleMetadataEvent(IntelliTraceEvent ev)
        {
            ModuleMetadataEvent moduleMetadataEvent = ev as ModuleMetadataEvent;
            Debug.Assert(moduleMetadataEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", moduleMetadataEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Module id", moduleMetadataEvent.ModuleId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Trace debug token", moduleMetadataEvent.MethodToken.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Signature", FormatBlob(moduleMetadataEvent.SignatureBytes));

            DumpProperties(eventProperties);
        }

        public void ProcessInformationEvent(IntelliTraceEvent ev)
        {
            ProcessInformationEvent processInformationEvent = ev as ProcessInformationEvent;
            Debug.Assert(processInformationEvent != null);

            NameValueCollection eventProperties = new NameValueCollection();
            eventProperties.Add("Ordinal", processInformationEvent.Ordinal.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Name", processInformationEvent.ProcessName);
            eventProperties.Add("Command line", processInformationEvent.ProcessCommandLine);
            eventProperties.Add("Process id", processInformationEvent.ProcessId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Start time", DateTime.FromFileTime(processInformationEvent.ProcessCreationTime).ToString("MM/dd/yyyy HH:mm:ss.fffffff", CultureInfo.CurrentCulture));
            eventProperties.Add("Session id", processInformationEvent.SessionId.ToString(CultureInfo.CurrentCulture));
            eventProperties.Add("Process bit width", processInformationEvent.ProcessBitWidth.ToString(CultureInfo.CurrentCulture));

            DumpProperties(eventProperties);
        }
    }
}
